package com.xinz.srmi;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;

import com.xinz.shared.exception.NetworkException;


/***
 * 远程调用层  RemoteInvoker
 * 序列化层  Serializer
 * 传输层 InvokConnector
 * 
 * 传输层 Connector?
 * 序列化层  Serializer
 * 本地调用层 NativeInvoker
 * 序列化层  Serializer
 * 传输层 Connector?
 * 
 * 传输层 InvokConnector
 * 序列化层  Serializer
 * 远程调用层  RemoteInvoker
 * @author xingyun
 *
 */
public class RemoteInvoker implements InvocationHandler {
	
	
//	Serializer serializer;
//	
	InvokeConnector connector;
//	
	Object responseHeader;
//	RemoteInvokListener.ListListener listeners = new ListListener();
	ConfigFactory foctyoy;
	
	
//	RequestHeaderProvider headerProvider;
	public RemoteInvoker(RequestHeaderProvider headerProvider, Serializer serializer,
			InvokeConnector connector) {
		super();
//		this.headerProvider = headerProvider;
//		this.serializer = serializer;
//		this.connector = connector;
	}
	public RemoteInvoker(ConfigFactory foctyoy, InvokeConnector connector) {
		this.connector = connector;
		this.foctyoy = foctyoy;
	}
//	public void addListener(RemoteInvokListener listener){
//		listeners.add(listener);
//	}
	
	@SuppressWarnings("unchecked")
	public <T> T getImplement(Class<T> clazz){
		if(!clazz.isInterface()) throw new RuntimeException("class :"+clazz+"不是一个接口");
		return (T) Proxy.newProxyInstance(RemoteInvoker.class.getClassLoader(), new Class[]{clazz}, 
				this);
	}
	long start;
	long curr;
	private void logTime(String tag){
		curr = System.currentTimeMillis();
//		Log.info(tag+(curr-start));
		start = curr;
	}
	@Override
	public Object invoke(Object arg0, Method method, Object[] args)
			throws Throwable {
		//调用序列化层，把方法调用的细节序列化层字节数组
		start = System.currentTimeMillis();
		RequestHeaderProvider provider = foctyoy.getNativeConfig().getRequestHeaderProvider();
		RemoteInvokeListener listener = foctyoy.getNativeConfig().getRemoteInvokListener(); 
		Serializer serializer = foctyoy.getShareConfig().getSerializer();
		Session session = connector.getSession();
		Object header = provider.provideRequestHeader(session,method,responseHeader,args);
		listener.onBeginInvok(method,args);
		Object[] responseHeader = new Object[1];
		try{
			
			Buffer request = serializer.methodToBuffer(session,method,header,args);
//			logTime(method.getName()+" ToBuffer:");
			//请求服务器

			Buffer resultBuffer = connector.request(request);
			if(resultBuffer==null){
				listener.onInvokSuccess(responseHeader[0],null);
				return null;
			}
//			logTime(method.getName()+" request:");
			Object result;
			result = serializer.parseReturn(session,resultBuffer,responseHeader);
//			logTime(method.getName()+" parseReturn size:"+resultBuffer.length+" time:");
			listener.onInvokSuccess(responseHeader[0],result);
			//解析返回结果，如果有异常则直接在解析层抛出
			return result;
		}catch (Throwable e) {
			listener.onInvokException(responseHeader[0],e);
			throw e;
		}finally{
			this.responseHeader = responseHeader[0];
		}
		
	}
}
